package members

import (
	"context"
	"dash/collectors"
	"dash/messages"
	"dash/watch"
	"errors"
	"fmt"

	"github.com/go-kit/kit/log"
	"github.com/go-redis/redis/v8"
)

// 网民相关的服务接口
type MemberService interface {
	// 获取人卡片
	Card(ctx context.Context, id string) (messages.Member, error)
	// 获取人详情
	Detail(ctx context.Context, id string) (messages.Member, error)
	// member对象的修改，仅可修改网民的可编辑部分
	UpdateMember(ctx context.Context, member messages.Member) (*messages.Member, error)
	// 获取member对象与关联user的关注状态
	GetMemberWatchedStatus(ctx context.Context, id, userId string) (bool, error)
}

type defaultMemberService struct {
	logger        log.Logger
	repo          Repository
	watchRepo 	 watch.WatchRepository
}

// 采集器关联采集用户的服务接口
type CollectorUserService interface{
	// 获取采集器关联的采集用户
	Users(ctx context.Context, collector collectors.Collector) ([]CollectorUser, error)
}

type collectorUserService struct{
	repo  	CollectorUserRepository
}

func NewCollectorUserService(repo CollectorUserRepository) CollectorUserService{
	return &collectorUserService{
		repo: repo,
	}
}

// 通过采集号Id获取关联的采集用户
func (svc *collectorUserService) Users(ctx context.Context, collector collectors.Collector) ([]CollectorUser, error){
	users, err := svc.repo.GetUserByCollectorId(ctx, collector.Id)
	if err != nil{
		return nil, err
	}
	return users, nil
}

// Card通过仓储服务取出card信息相关的member对象
func (d *defaultMemberService) Card(ctx context.Context, id string) (messages.Member, error) {
	if len(id) == 0 {
		return messages.Member{}, errors.New("用户id不能为空")
	}
	// 根据id获取member对象
	member, err := d.repo.Get(ctx, id)
	if err != nil {
		return messages.Member{}, err
	}
	// 通过仓储服务获取该网民的七天发言量
	messageCount7, err := d.repo.GetMessageCount7(ctx, fmt.Sprintf("dailyMemberMsgCount:%s", id))
	if err != nil && err != redis.Nil {
		_ = d.logger.Log("get redis member error:", err)
		_ = err
	}
	member.MessageCount7 = messageCount7
	return member, nil
}

// Detail通过仓储获得详情相关的member对象
func (d *defaultMemberService) Detail(ctx context.Context, id string) (messages.Member, error) {
	if len(id) == 0 {
		return messages.Member{}, errors.New("用户id不能为空")
	}
	// 根据id获取member对象
	member, err := d.repo.Get(ctx, id)
	if err != nil {
		return messages.Member{}, err
	}
	// 通过仓储获取该网民的7天发言量
	messageCount7, err := d.repo.GetMessageCount7(ctx, fmt.Sprintf("dailyMemberMsgCount:%s", id))
	if err != nil && err != redis.Nil {
		_ = d.logger.Log("get redis member error:", err)
		_ = err
	}
	// 获取该网民的7天预警发言量
	alarmCount, err := d.repo.GetAlarmMessageCount7(ctx, id)
	if err != nil {
		_ = d.logger.Log("get es member error:", err)
		_ = err
	}
	// 通过仓储获取该网民最新的发言时间
	lastMsgTime, err := d.repo.GetLastMessageTimestamp(ctx, id)
	if err != nil && err != redis.Nil {
		_ = d.logger.Log("get redis member error:", err)
	}
	member.MessageCount7 = messageCount7
	member.AlarmCount7 = alarmCount
	member.LastMessageTimestamp = lastMsgTime
	for i, c := range member.Chatrooms{
		// 通过仓储获取该网民所在群的7天消息量
		// 通过索引进行修改，避免值对象的复制c无法对原数据进行修改
		member.Chatrooms[i].MessageCount, err = d.repo.GetMessageCount7(ctx, fmt.Sprintf("dailyChatroomMsgCount:%s", c.Id))
		if err != nil{
			_ = d.logger.Log("get message count error", err.Error())
		}
	}
	return member, nil
}

// 更改网民的相关服务
func (d *defaultMemberService) UpdateMember(ctx context.Context, member messages.Member) (*messages.Member, error){
	err := d.repo.Save(ctx, member)
	if err != nil{
		return nil, err
	}
	return &member, nil
}

func (d *defaultMemberService) GetMemberWatchedStatus(ctx context.Context, id, userId string) (bool, error){
	return d.watchRepo.GetMemberWatchedStatus(ctx, id, userId)
}

func NewMemberService(logger log.Logger, repo Repository, watchRepo watch.WatchRepository) *defaultMemberService {
	return &defaultMemberService{
		logger: logger,
		repo:   repo,
		watchRepo: watchRepo,
	}
}
